/**
 *Author: Jiangtao He; Email: ross.jiangtao.he@gmail.com
 *File Name: HttpDownloadTool.java
 *Date: 2012-1-18
 *Copyright: All right reserved by author - Jiangtao He
 *Version: MyJavaExpert v1.0
 */
package com.ross.httpdownload;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.*;
import java.util.concurrent.*;

import com.ross.httpdownload.util.HttpProcess;
import com.ross.httpdownload.util.SysValue;

/**
 * Author: Jiangtao He; Email: ross.jiangtao.he@gmail.com
 * Date: 2012-1-18
 * Since: MyJavaExpert v1.0
 * Description: It will be the entry of the http download tool.
 */
public class HttpDownloadTool
{
    private HttpProcess oHttpProcess;

    /**
     * Description: default constructor, it is used for initializing the fields.
     */
    public HttpDownloadTool()
    {
        oHttpProcess = new HttpProcess();
    }

    /**
     * Author: Jiangtao He; Email: ross.jiangtao.he@gmail.com
     * Description: download tool entry method
     * @param sURL: the completed URL of the file, which is wanted to download. 
     * @param Num: Number of concurrent download thread
     * @param sSaveAsName: the the file name saved in disk, like: myphoto.jpg
     */
    public void download(String sURL, int iNumOfThread, String sSaveAsName)
    {
        long lFileLen = 0;
        long lFileSegementLen = 0;
        long iLeft = 0;
        URLConnection oURLCon = null;
        String sFullFileName = SysValue.Save_As_Path + sSaveAsName;

        if (iNumOfThread > SysValue.MAX_Num_Of_Thread)
        {
            iNumOfThread = SysValue.MAX_Num_Of_Thread;
        }
        if (iNumOfThread < 1)
        {
            iNumOfThread = 1;
        }

        // build the thread pool to manage the thread
        ExecutorService oExecService = Executors
                .newFixedThreadPool(iNumOfThread);
        try
        {
            if (!isSupportMultipleThreadDown(sURL))
            {
                System.out
                        .println("This site do not support multiple thread download, reset the thread to 1");
                iNumOfThread = 1;
            }

            // get URL connection
            oURLCon = oHttpProcess.getURLConnection(sURL);
            // get the length of the file
            lFileLen = oURLCon.getContentLength();
            // split the length of the file according to the number of thread.
            lFileSegementLen = lFileLen / iNumOfThread;
            iLeft = lFileLen % iNumOfThread;

            for (int i = 0; i < iNumOfThread; i++)
            {
                // initial the thread data
                DownloadThread oDownloadThread = new DownloadThread();
                oDownloadThread.setIThreadId(i);
                // Start index of the current thread
                oDownloadThread.setLStartIndex(i * lFileSegementLen);

                // last thread will take all the rest content
                if (i == (iNumOfThread - 1))
                {
                    oDownloadThread.setLEndIndex((i + 1) * lFileSegementLen
                            + iLeft - 1);
                }
                else
                {
                    oDownloadThread
                            .setLEndIndex((i + 1) * lFileSegementLen - 1);
                }
                // set save file name with path
                oDownloadThread.setSFullFileName(sFullFileName);
                // set URL
                oDownloadThread.setSFileURL(sURL);
                // execute the download thread
                oExecService.execute(oDownloadThread);
            }
            System.out.println("the file is stored as \"" + sFullFileName
                    + "\".");
            System.out.println("the file length is " + lFileLen + ".");
        }
        catch (IOException e)
        {
            System.out.println("download the file failed, IO Exception"
                    + e.getMessage());
            e.printStackTrace();
        }
        finally
        {
            oExecService.shutdown();
        }
    }
    /**
     * Description: Check whether the server support multiple thread download or not
     * @param sURL: the download file URL
     * @return bRet: true - support, false - not support
     * @throws IOException 
     */
    public boolean isSupportMultipleThreadDown(String sURL) throws IOException
    {
        boolean bRet = true;
       // get URL connection
        URLConnection oURLCon = oHttpProcess.getURLConnection(sURL);
       // set the resource range
        oURLCon.setRequestProperty("Range", "bytes=" + 0 + "-" + 1023);

        if (1024 < oURLCon.getContentLength())
        {
            bRet = false;
        }
        return bRet;
    }
}
